﻿using System;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using NUnit.Framework;
using Smith.BuildExtensions.ConfigurationTransformation;
using Assert = NUnit.Framework.Assert;

namespace BuildExtensionsTests
{
    [TestClass]
    public class ConfigSettingsTest
    {
        [TestMethod]
        public void ShouldBeAbleToLoadFromFileWithoutAdd()
        {
            const string Config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings>
    <addsection key=""HostName"" overwritable=""true""><value>test</value></addsection>
    <addsection key=""FullUrl"" overwritable=""true""><value>http://$(HostName)/test</value></addsection>
</settings>";

            string fn = "config." + Guid.NewGuid() + ".config";
            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);
            try
            {

                File.WriteAllText(templateFileName, Config);

                ConfigSettings settings = ConfigSettings.LoadFromFile(templateFileName);

                ConfigSetting hostSetting = settings.Settings.FirstOrDefault(s => s.Key == "HostName");
                ConfigSetting urlSetting = settings.Settings.FirstOrDefault(s => s.Key == "FullUrl");

                Assert.That(hostSetting, Is.Not.Null);
                Assert.That(urlSetting, Is.Not.Null);

                Assert.That(hostSetting.Value, Is.Not.Null);
                Assert.That(urlSetting.Value, Is.Not.Null);
            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);
                }
                catch
                {
                }
            }
        }

        [TestMethod]
        public void ShouldBeAbleToLoadFromFileWithoutAddSection()
        {
            const string Config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings>
    <add key=""HostName"" value=""http://localhost/dev"" overwritable=""true""/>
    <add key=""FullUrl"" value=""$(HostName)/Services/test.aspx"" overwritable=""true""/>
</settings>";
            string fn = "config." + Guid.NewGuid() + ".config";

            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);
            try
            {

                File.WriteAllText(templateFileName, Config);

                ConfigSettings settings = ConfigSettings.LoadFromFile(templateFileName);
                Assert.That(settings.Settings.FirstOrDefault(s => s.Key == "HostName"), Is.Not.Null);
                Assert.That(settings.Settings.FirstOrDefault(s => s.Key == "FullUrl"), Is.Not.Null);
            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);
                }
                catch
                {
                }
            }

        }

        [TestMethod]
        public void ShouldBeAbleToLoadFromFileWithBothTypes()
        {
            const string Config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings>
    <addsection key=""HostName"" overwritable=""true""><value>test</value></addsection>
    <addsection key=""FullUrl"" overwritable=""true""><value>http://$(HostName)/test</value></addsection>
<add key=""UserName"" value=""bjsmi"" overwritable=""true""/>
</settings>";

            string fn = "config." + Guid.NewGuid() + ".config";
            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);
            try
            {

                File.WriteAllText(templateFileName, Config);

                ConfigSettings settings = ConfigSettings.LoadFromFile(templateFileName);

                ConfigSetting hostSetting = settings.Settings.FirstOrDefault(s => s.Key == "HostName");
                ConfigSetting urlSetting = settings.Settings.FirstOrDefault(s => s.Key == "FullUrl");
                ConfigSetting userNameSetting = settings.Settings.FirstOrDefault(s => s.Key == "UserName");

                Assert.That(hostSetting, Is.Not.Null);
                Assert.That(urlSetting, Is.Not.Null);
                Assert.That(userNameSetting, Is.Not.Null);

                Assert.That(hostSetting.Value, Is.Not.Null);
                Assert.That(urlSetting.Value, Is.Not.Null);
                Assert.That(userNameSetting.Value, Is.Not.Null);
            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);
                }
                catch
                {
                }
            }
        }

        [TestMethod]
        public void ShouldBeAbleToLoadFromEmpty()
        {
            const string Config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings/>";

            string fn = "config." + Guid.NewGuid() + ".config";
            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);
            try
            {

                File.WriteAllText(templateFileName, Config);

                ConfigSettings settings = ConfigSettings.LoadFromFile(templateFileName);
                Assert.That(settings.Settings.Count, Is.EqualTo(0));
            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);
                }
                catch
                {
                }
            }
        }


        [TestMethod]
        public void IfConfigSettingsDefineFileSourceThatFileShouldBeLoadedInstead()
        {
            string fn = "config." + Guid.NewGuid() + ".config";
            string fn2 = "config." + Guid.NewGuid() + ".config";
            string configLoadFrom = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings ConfigSource=""" + fn2 + @"""/>";

            const string Config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings>
    <add key=""HostName"" value=""http://localhost/dev"" overwritable=""true""/>
    <add key=""FullUrl"" value=""$(HostName)/Services/test.aspx"" overwritable=""true""/>
</settings>";



            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);
            string templateFileName2 = Path.Combine(Environment.CurrentDirectory, fn2);
            try
            {

                File.WriteAllText(templateFileName, configLoadFrom);
                File.WriteAllText(templateFileName2, Config);

                ConfigSettings settings = ConfigSettings.LoadFromFile(templateFileName);
                Assert.That(settings.Settings.Count, Is.EqualTo(2));
            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);
                    File.Delete(templateFileName2);
                }
                catch
                {
                }
            }
        }

        [TestMethod]
        public void IfConfigSettingsDefineFileSourceThatContainsACyclicDepencendyInvalidOperationExceptionShouldBeThrown()
        {
            string fn = "config." + Guid.NewGuid() + ".config";

            string configLoadFrom = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<settings ConfigSource=""" + fn + @"""/>";

            string templateFileName = Path.Combine(Environment.CurrentDirectory, fn);

            try
            {

                File.WriteAllText(templateFileName, configLoadFrom);

                Assert.Throws<InvalidOperationException>(() => ConfigSettings.LoadFromFile(templateFileName));

            }
            finally
            {
                try
                {
                    File.Delete(templateFileName);

                }
                catch
                {
                }
            }
        }
    }
}
